local modid = 'yuemiheng'

local start_level = TUNING[string.upper('CONFIG_'..modid..'_startlv')]

local function on_lv_cur(self, value)
    self.inst.replica.ymh_lv:set_lv_cur(value)
end

local function on_exp_cur_max(self, value)
    self.inst.replica.ymh_lv:set_exp_cur_max(value)
end

local function on_exp_cur(self, value)
    self.inst.replica.ymh_lv:set_exp_cur(value)
end

local ymh_lv = Class(function(self, inst)
    self.inst = inst
    -- self.val = 0

    self.lv_cur = 0 -- 初始等级为0
    self.exp_cur_max = 0 --经验条总量
    self.exp_cur = 0 --当前经验条


    inst:ListenForEvent('killed',
    ---comment
    ---@param inst ent
    ---@param data any
    function (inst,data)
        local victim = data and data.victim
        if victim and not victim:HasTag("structure") and not victim:HasTag("wall") then
            local maxhp = victim and victim.components.health and victim.components.health.maxhealth
            local exp = maxhp and maxhp/TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.PER_EXP_FROM_MOB_HP
            if exp then
                if inst.components.ymh_lv then
                    inst.components.ymh_lv:GetExp(exp)
                end
            end
        end
    end)

    inst:DoPeriodicTask(TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.AUTOREGEN_INTERVAL,function(inst)
        if YMHS:checkAlive(inst) and inst.components.ymh_lv then
            local lv_cur = inst.components.ymh_lv.lv_cur
            if lv_cur and lv_cur>0 then
                local regen_hp = math.min(lv_cur * TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.AUTOREGEN_PER,TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.AUTOREGEN_PER_MAX)
                inst.components.health:DoDelta(regen_hp,true)
            end
        end
    end)

    if start_level > 0 then
        local need_exp = self:_GetExpToLevel(start_level)
        -- inst:DoTaskInTime(0,function()
            self:GetExp(need_exp)
            if not TheWorld.ismastersim and ThePlayer then
                ThePlayer:PushEvent('ymh_lv_exp_cur_change')
            end
        -- end)
    end
end,
nil,
{
    -- val = on_val,
    lv_cur = on_lv_cur,
    exp_cur_max = on_exp_cur_max,
    exp_cur = on_exp_cur,
})

function ymh_lv:OnSave()
    return {
        -- val = self.val,
        lv_cur = self.lv_cur,
        exp_cur_max = self.exp_cur_max,
        exp_cur = self.exp_cur,
    }
end

function ymh_lv:OnLoad(data)
    -- self.val = data.val or 0
    self.lv_cur = data.lv_cur or 0
    self.exp_cur_max = data.exp_cur_max or 0
    self.exp_cur = data.exp_cur or 0

    if self.lv_cur > 0 then
        self:Add3Size(self.lv_cur)
    end

    self:UnlockItemTransfer()
end

---获取多少经验到某等级
---@param level integer
---@return number
---@nodiscard
function ymh_lv:_GetExpToLevel(level)
    local exp_per_level = TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.BAR
    if level <= 0 then
        return 0
    end
    return exp_per_level * level
end

function ymh_lv:GetExp(delta) --当获取经验
    local old_lv = self.lv_cur

    self.exp_cur_max = TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.BAR
    self.exp_cur = self.exp_cur + delta
    local dolvlup = false
    while self.exp_cur > 0 do
        --如果当前经验值大于等于经验条总量,即满足升级条件,则逐级升级,否则跳出循环
        if self.exp_cur >= self.exp_cur_max then 
            self.exp_cur = self.exp_cur - self.exp_cur_max
            self.lv_cur = self.lv_cur + 1
            dolvlup = true --如果玩家升级了
            self.exp_cur_max = TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.BAR
        else
            break
        end
    end
    if dolvlup then --若玩家升级了,才会加三围
        local delta_lv = self.lv_cur - old_lv
        self:Add3Size(delta_lv)
    end

    -- hint
    if self.inst.components.talker then
        local content = 'LV: ' .. self.lv_cur .. ' EXP: '.. self.exp_cur
        self.inst.components.talker:Say(content,2,true,nil)
    end

    -- 闪电
    if self.lv_cur > 0 then
        self:Lightning()
    end

    self:UnlockItemTransfer()
    -- print("等级为："..self.lv_cur)
    -- print("当前经验值为："..self.exp_cur.."/"..self.exp_cur_max)
end

function ymh_lv:Add3Size(delta_lv)
    self.inst.components.hunger.max = math.ceil(self.inst.components.hunger.max + delta_lv*TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.MAX_HUNGER_PER_LV)
    self.inst.components.health.maxhealth = math.ceil(self.inst.components.health.maxhealth + delta_lv*TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.MAX_HEALTH_PER_LV)
end

function ymh_lv:Lightning()
    if (self.lv_cur%TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_120_LV) <= 0 then
        local count = 0
        self.inst.taskperiod_ymh_lightning = self.inst:DoPeriodicTask(TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_120_INTERVAL,function(inst)
            if count > TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_120_NUM then
                if inst.taskperiod_ymh_lightning then
                    inst.taskperiod_ymh_lightning:Cancel()
                    inst.taskperiod_ymh_lightning = nil
                end
                return
            end
            count = count + 1
            SpawnPrefab("lightning").Transform:SetPosition(inst:GetPosition():Get())
            if inst.components.playerlightningtarget then
                inst.components.health:DoDelta(-TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_120_DMG, false, "lightning")
                if not inst.sg:HasStateTag("dead") then
                    inst.sg:GoToState("electrocute")
                end
            end
        end)
    elseif (self.lv_cur%TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_60_LV) <= 0 then
        local count = 0
        self.inst.taskperiod_ymh_lightning = self.inst:DoPeriodicTask(TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_60_INTERVAL,function(inst)
            if count > TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_60_NUM then
                if inst.taskperiod_ymh_lightning then
                    inst.taskperiod_ymh_lightning:Cancel()
                    inst.taskperiod_ymh_lightning = nil
                end
                return
            end
            count = count + 1
            SpawnPrefab("lightning").Transform:SetPosition(inst:GetPosition():Get())
            if inst.components.playerlightningtarget then
                inst.components.health:DoDelta(-TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_60_DMG, false, "lightning")
                if not inst.sg:HasStateTag("dead") then
                    inst.sg:GoToState("electrocute")
                end
            end
        end)
    elseif (self.lv_cur%TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_10_LV) <= 0 then
        local count = 0
        self.inst.taskperiod_ymh_lightning = self.inst:DoPeriodicTask(TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_10_INTERVAL,function(inst)
            if count > TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_10_NUM then
                if inst.taskperiod_ymh_lightning then
                    inst.taskperiod_ymh_lightning:Cancel()
                    inst.taskperiod_ymh_lightning = nil
                end
                return
            end
            count = count + 1
            SpawnPrefab("lightning").Transform:SetPosition(inst:GetPosition():Get())
            if inst.components.playerlightningtarget then
                inst.components.health:DoDelta(-TUNING.MOD_YUEMIHENG.AVATAR.YUEMIHENG.EXP.LIGHTNING_10_DMG, false, "lightning")
                if not inst.sg:HasStateTag("dead") then
                    inst.sg:GoToState("electrocute")
                end
            end
        end)
    end
end

function ymh_lv:UnlockItemTransfer()
    if self.lv_cur >= 20 then
        if not self.inst:HasTag('yuemiheng_lv20') then
            self.inst:AddTag('yuemiheng_lv20')
        end
    end
end

return ymh_lv